package pers.qianyu.exception.handler;

import cn.hutool.log.*;
import com.alibaba.fastjson.*;
import org.springframework.http.*;
import org.springframework.validation.*;
import org.springframework.web.bind.*;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.*;
import pers.qianyu.exception.*;
import pers.qianyu.module.core.comm.*;

import javax.validation.*;
import java.util.*;
import java.util.stream.*;

@ControllerAdvice
public class GlobalExceptionHandler {


    /**
     * 处理方法参数校验异常
     *
     * @param ex 异常对象
     * @return 响应信息
     */
    @ResponseBody
    @ExceptionHandler(ConstraintViolationException.class)
    @ResponseStatus(HttpStatus.OK)
    public HttpResult<?> constraintViolationExceptionExceptions(ConstraintViolationException ex) {
        String message = ex.getConstraintViolations()
                .stream()
                .map(c -> Arrays.toString(c.getExecutableParameters()) + c.getMessage())
                .collect(Collectors.joining());
        LogFactory.get().error("{}", ex.toString());
        ex.printStackTrace();
        HttpResult<?> httpResult = HttpResult.error(GlobalErrorCodeEnum.INVALID_PARAMETERS);
        httpResult.setMessage(message);
        return httpResult;
    }

    @ResponseBody
    @ExceptionHandler(ValidationException.class)
    @ResponseStatus(HttpStatus.OK)
    public HttpResult<?> validationExceptionExceptionExceptions(ValidationException ex) {
        LogFactory.get().error("ValidationException: {}", ex.toString());
        ex.printStackTrace();
        return HttpResult.error(GlobalErrorCodeEnum.INVALID_PARAMETERS);
    }

    /**
     * 处理方法参数校验异常
     *
     * @param ex 异常对象
     * @return 响应信息
     */
    @ResponseBody
    @ExceptionHandler(MethodArgumentNotValidException.class)
    @ResponseStatus(HttpStatus.OK)
    public HttpResult<?> handleValidationExceptions(MethodArgumentNotValidException ex) {
        Map<String, String> errors = new HashMap<>();
        ex.getBindingResult().getAllErrors().forEach((error) -> {
            String fieldName = ((FieldError) error).getField();
            String errorMessage = error.getDefaultMessage();
            errors.put(fieldName, errorMessage);
        });
        LogFactory.get().error("{}: {}", ex.getClass().getName(), JSON.toJSONString(errors));
        ex.printStackTrace();
        HttpResult<?> httpResult = HttpResult.error(GlobalErrorCodeEnum.INVALID_PARAMETERS);
        httpResult.setMessage(errors.toString());
        return httpResult;
    }

    /**
     * 处理系统中自定义异常
     *
     * @param ex 异常对象
     * @return 响应信息
     */
    @ResponseBody
    @ExceptionHandler(value = LambBaseException.class)
    @ResponseStatus(HttpStatus.OK)
    public HttpResult<?> lambBaseExceptionHandler(LambBaseException ex) {
        LogFactory.get().error("{}:{}", ex.getClass().getName(), ex.getMessage());
        ex.printStackTrace();
        return HttpResult.error(ex);
    }

    /**
     * 处理找不到资源异常
     *
     * @param ex 异常对象
     * @return 响应信息
     */
    @ResponseBody
    @ExceptionHandler(value = NoHandlerFoundException.class)
    @ResponseStatus(HttpStatus.NOT_FOUND)
    public HttpResult<?> noHandlerFoundExceptionHandler(NoHandlerFoundException ex) {
        LogFactory.get().error("{}:{}", ex.getClass().getName(), ex.getMessage());
        ex.printStackTrace();
        return HttpResult.error(GlobalErrorCodeEnum.RESOURCES_NOT_FOUND);
    }

    /**
     * 处理其他异常
     *
     * @param th 错误对象
     * @return 响应信息
     */
    @ResponseBody
    @ExceptionHandler(value = Exception.class)
    @ResponseStatus(HttpStatus.SERVICE_UNAVAILABLE)
    public HttpResult<?> exceptionHandler(Throwable th) {
        th.printStackTrace();
        return HttpResult.error(GlobalErrorCodeEnum.SYS_ERROR);
    }
}